package top.codedance.iotp.tools.terminal.ui;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import top.codedance.iotp.common.constent.Command;
import top.codedance.iotp.common.util.HexCodec;
import top.codedance.iotp.common.util.JsonUtil;
import top.codedance.iotp.common.util.SystemUtil;
import top.codedance.iotp.tools.terminal.TerminalApplication;
import top.codedance.iotp.tools.terminal.bean.ComConnectParam;
import top.codedance.iotp.tools.terminal.comer.CallOwner;
import top.codedance.iotp.tools.terminal.comer.ComClient;

import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import javax.xml.bind.DatatypeConverter;
import java.awt.*;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.InputEvent;
import java.awt.event.ItemEvent;
import java.net.URL;
import java.util.*;

/**
 *
 * @author xuedianfu
 */
public class ClientPluginTester extends javax.swing.JDialog implements CallOwner {
    public ShellFrame sf;
    public JSONObject currentConnectionParam;
    public JSONObject connectData = new JSONObject();
    private DefaultComboBoxModel<String> dlmB;
    private DefaultTableModel tm;
    private String[] colums = new String[]{"名称", "数据"};
    private String[][] tableData = new String[][]{};
    private final int DATA_INDEX = 1;
    public static short RUNNER_TYPE = 1;
    private WaitLoading waitLoading = new WaitLoading(this);
    private HexCodec hc = new HexCodec();

    /**
     * Creates new form ClientPluginTester
     */
    public ClientPluginTester(ShellFrame sf) {
        super(sf, true);
        this.sf = sf;
        initComponents();
        URL url = Thread.currentThread().getContextClassLoader().getResource("logo.gif");
        ImageIcon icon = new ImageIcon(url);
        setIconImage(icon.getImage());
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        setLocationRelativeTo(null);
        setMinimumSize(new Dimension(900, 600));
        setTitle("代码飞舞采控系统-客户端插件测试器");
        addComponentListener(new ComponentAdapter() {
            @Override
            public void componentResized(ComponentEvent e) {
                resetComponent();
            }
        });
        resetComponent();
        initMenuBar();
        initList();
        initResultTable();
        initRequesItemtOprationMenus();
    }

    public ShellFrame getShellFrame(){
        return this.sf;
    }

    private void resetComponent(){
        jSplitPane1.setDividerLocation(0.5);
    }

    private JPopupMenu paramHelpJpm;

    private void initRequesItemtOprationMenus() {
        paramHelpJpm = new JPopupMenu();
        JMenuItem mi_del = new JMenuItem("删除");
        mi_del.setOpaque(true);
        mi_del.setBackground(new java.awt.Color(255, 51, 51));
        mi_del.setForeground(new java.awt.Color(255, 255, 255));
        mi_del.addActionListener(e -> {
            int[] selectedRows = jt_result.getSelectedRows();
            Arrays.sort(selectedRows);
            for(int i = selectedRows.length -1; i >=0; i--) {
                tm.removeRow(selectedRows[i]);
            }
        });
        paramHelpJpm.add(mi_del, 0);
        JMenuItem mi_edit = new JMenuItem("编辑");
        mi_edit.addActionListener(e -> {
            JSONObject currentSelectedPluginCommandData = getCurrentSelectedPluginCommandData();
            switch (currentSelectedPluginCommandData.getShortValue("plugin")) {
                case Command.MODBUS_COMMAND:
                    AddModbus addModbus = new AddModbus(ClientPluginTester.this, currentSelectedPluginCommandData);
                    addModbus.setLocationRelativeTo(ClientPluginTester.this);
                    addModbus.setVisible(true);
                    break;
                case Command.BACNET_COMMAND:
                    AddBacNet addBacNet = new AddBacNet(ClientPluginTester.this, currentSelectedPluginCommandData);
                    addBacNet.setLocationRelativeTo(ClientPluginTester.this);
                    addBacNet.setVisible(true);
                    break;
                case Command.OPC_COMMAND:
                    AddOpc addOpc = new AddOpc(ClientPluginTester.this, currentSelectedPluginCommandData);
                    addOpc.setLocationRelativeTo(ClientPluginTester.this);
                    addOpc.setVisible(true);
                    break;
                case Command.COM_COMMAND:
                    AddCom addCom = new AddCom(ClientPluginTester.this, currentSelectedPluginCommandData);
                    addCom.setLocationRelativeTo(ClientPluginTester.this);
                    addCom.setVisible(true);
                    break;
                case Command.UDP_COMMAND:
                    AddUdp addUdp = new AddUdp(ClientPluginTester.this, currentSelectedPluginCommandData);
                    addUdp.setLocationRelativeTo(ClientPluginTester.this);
                    addUdp.setVisible(true);
                    break;
                case Command.HTTP_COMMAND:
                    AddHttp addHttp = new AddHttp(ClientPluginTester.this, currentSelectedPluginCommandData);
                    addHttp.setLocationRelativeTo(ClientPluginTester.this);
                    addHttp.setVisible(true);
                    break;
                case Command.PUSH_DATA_COMMAND:
                    AddPushData addPushData = new AddPushData(ClientPluginTester.this, currentSelectedPluginCommandData);
                    addPushData.setLocationRelativeTo(ClientPluginTester.this);
                    addPushData.setVisible(true);
                    break;
                case Command.GENERICDB_COMMAND:
                    AddGenericDB addGenericDB = new AddGenericDB(ClientPluginTester.this, currentSelectedPluginCommandData);
                    addGenericDB.setLocationRelativeTo(ClientPluginTester.this);
                    addGenericDB.setVisible(true);
                    break;
                case Command.MYSQL_COMMAND:
                    AddMysql addMysql = new AddMysql(ClientPluginTester.this, currentSelectedPluginCommandData);
                    addMysql.setLocationRelativeTo(ClientPluginTester.this);
                    addMysql.setVisible(true);
                    break;
                case Command.MSSQL_COMMAND:
                    AddMssql addMssql = new AddMssql(ClientPluginTester.this, currentSelectedPluginCommandData);
                    addMssql.setLocationRelativeTo(ClientPluginTester.this);
                    addMssql.setVisible(true);
                    break;
                case Command.ORACLE_COMMAND:
                    AddOracle addOracle = new AddOracle(ClientPluginTester.this, currentSelectedPluginCommandData);
                    addOracle.setLocationRelativeTo(ClientPluginTester.this);
                    addOracle.setVisible(true);
                    break;
                case Command.CLIENT_PLUGINS_PARAMS_SET:
                case Command.CLIENT_PLUGINS_PARAMS_GET:
                    AddPluginParams addPluginParams = new AddPluginParams(ClientPluginTester.this, currentSelectedPluginCommandData);
                    addPluginParams.setLocationRelativeTo(ClientPluginTester.this);
                    addPluginParams.setVisible(true);
                    break;
                case Command.CLIENT_BOOT_PARAMS_SET:
                case Command.CLIENT_BOOT_PARAMS_GET:
                    AddClientBootParams addClientBootParams = new AddClientBootParams(ClientPluginTester.this, currentSelectedPluginCommandData);
                    addClientBootParams.setLocationRelativeTo(ClientPluginTester.this);
                    addClientBootParams.setVisible(true);
                    break;
                case Command.SHUTDOWN:
                    AddResetClient addResetClient = new AddResetClient(ClientPluginTester.this, currentSelectedPluginCommandData);
                    addResetClient.setLocationRelativeTo(ClientPluginTester.this);
                    addResetClient.setVisible(true);
                    break;
                default:
                    int i = JOptionPane.showConfirmDialog(rootPane, "命令内容不正确，是否要删除此条命令。");
                    if(JOptionPane.YES_OPTION == i){
                        tm.removeRow(jt_result.getSelectedRow());
                    }
                    break;
            }
        });
        paramHelpJpm.add(mi_edit, 1);
        jt_result.add(paramHelpJpm);
    }

    private void initResultTable(){
        tm = new DefaultTableModel(tableData, colums);
        jt_result.setModel(tm);
        jt_result.getTableHeader().setReorderingAllowed(false);
    }

    public void initList(){
        dlmB = new DefaultComboBoxModel<>();
        this.jcb_connections.setModel(dlmB);
        initListData();
    }

    public void initListData(){
        String s = SystemUtil.readTempFile(ConnectionManager.CONNECTION_TMP_FILENAME);
        if(null != s && !s.isEmpty()) {
            connectData = JSON.parseObject(s);
            dlmB.removeAllElements();
            Set<Map.Entry<String, Object>> entries = connectData.entrySet();
            JSONObject jo;
            for (Map.Entry<String, Object> entry : entries) {
                jo = (JSONObject)entry.getValue();
                if(jo.containsKey("type") && jo.getString("type").equals("com") && jo.containsKey("manage") && jo.getBoolean("manage")) {
                    dlmB.addElement(entry.getKey());
                }
            }
            this.jcb_connections.repaint();
            String key = (String)jcb_connections.getSelectedItem();
            currentConnectionParam = this.connectData.getJSONObject(key);
        }
    }

    private JSONObject getCurrentSelectedPluginCommandData(){
        if(jt_result.getSelectedRowCount() == 1) {
            int selectedRow = jt_result.getSelectedRow();
            String str = (String) tm.getValueAt(selectedRow, DATA_INDEX);
            try {
                JSONObject jsonObject = JSON.parseObject(str);
                jsonObject.put("rowIndex", selectedRow);
                return jsonObject;
            } catch (Exception e) {
                TerminalApplication.syslogInfo(e.getMessage());
                return null;
            }
        }else{
            return null;
        }
    }

    private void initMenuBar() {
        JMenu jm = new JMenu("配置客户端插件");
        JMenuItem jmi1 = new JMenuItem("BACNet");
        jmi1.addActionListener((event) -> {
            AddBacNet addBacNet = new AddBacNet(ClientPluginTester.this, null);
            addBacNet.setLocationRelativeTo(ClientPluginTester.this);
            addBacNet.setVisible(true);
        });
        jm.add(jmi1);
        JMenuItem jmi = new JMenuItem("Modbus");
        jmi.addActionListener((event) -> {
            AddModbus addModbus = new AddModbus(ClientPluginTester.this, null);
            addModbus.setLocationRelativeTo(ClientPluginTester.this);
            addModbus.setVisible(true);
        });
        jm.add(jmi);
        JMenuItem jmi2 = new JMenuItem("OPC");
        jmi2.addActionListener((event) -> {
            AddOpc addOpc = new AddOpc(ClientPluginTester.this, null);
            addOpc.setLocationRelativeTo(ClientPluginTester.this);
            addOpc.setVisible(true);
        });
        jm.add(jmi2);
        JMenuItem jmi3 = new JMenuItem("COM");
        jmi3.addActionListener((event) -> {
            AddCom addCom = new AddCom(ClientPluginTester.this, null);
            addCom.setLocationRelativeTo(ClientPluginTester.this);
            addCom.setVisible(true);
        });
        jm.add(jmi3);
        JMenuItem jmi13 = new JMenuItem("UDP");
        jmi13.addActionListener((event) -> {
            AddUdp addUdp = new AddUdp(ClientPluginTester.this, null);
            addUdp.setLocationRelativeTo(ClientPluginTester.this);
            addUdp.setVisible(true);
        });
        jm.add(jmi13);
        JMenuItem jmi4 = new JMenuItem("HTTP");
        jmi4.addActionListener((event) -> {
            AddHttp addHttp = new AddHttp(ClientPluginTester.this, null);
            addHttp.setLocationRelativeTo(ClientPluginTester.this);
            addHttp.setVisible(true);
        });
        jm.add(jmi4);
        JMenuItem jmi11 = new JMenuItem("推送的数据");
        jmi11.addActionListener((event) -> {
            AddPushData addPushData = new AddPushData(ClientPluginTester.this, null);
            addPushData.setLocationRelativeTo(ClientPluginTester.this);
            addPushData.setVisible(true);
        });
        jm.add(jmi11);
        JMenuItem jmi12 = new JMenuItem("GenericDB");
        jmi12.addActionListener((event) -> {
            AddGenericDB addGenericDB = new AddGenericDB(ClientPluginTester.this, null);
            addGenericDB.setLocationRelativeTo(ClientPluginTester.this);
            addGenericDB.setVisible(true);
        });
        jm.add(jmi12);
        JMenuItem jmi5 = new JMenuItem("MYSQL");
        jmi5.addActionListener((event) -> {
            AddMysql addMysql = new AddMysql(ClientPluginTester.this, null);
            addMysql.setLocationRelativeTo(ClientPluginTester.this);
            addMysql.setVisible(true);
        });
        jm.add(jmi5);
        JMenuItem jmi6 = new JMenuItem("MSSQL");
        jmi6.addActionListener((event) -> {
            AddMssql addMssql = new AddMssql(ClientPluginTester.this, null);
            addMssql.setLocationRelativeTo(ClientPluginTester.this);
            addMssql.setVisible(true);
        });
        jm.add(jmi6);
        JMenuItem jmi7 = new JMenuItem("ORACLE");
        jmi7.addActionListener((event) -> {
            AddOracle addOracle = new AddOracle(ClientPluginTester.this, null);
            addOracle.setLocationRelativeTo(ClientPluginTester.this);
            addOracle.setVisible(true);
        });
        jm.add(jmi7);
        JMenuItem jmi8 = new JMenuItem("客户端插件参数");
        jmi8.addActionListener((event) -> {
            AddPluginParams addPluginParams = new AddPluginParams(ClientPluginTester.this, null);
            addPluginParams.setLocationRelativeTo(ClientPluginTester.this);
            addPluginParams.setVisible(true);
        });
        jm.add(jmi8);
        JMenuItem jmi9 = new JMenuItem("客户端启动参数");
        jmi9.addActionListener((event) -> {
            AddClientBootParams addClientBootParams = new AddClientBootParams(ClientPluginTester.this, null);
            addClientBootParams.setLocationRelativeTo(ClientPluginTester.this);
            addClientBootParams.setVisible(true);
        });
        jm.add(jmi9);
        JMenuItem jmi10 = new JMenuItem("重启客户端");
        jmi10.addActionListener((event) -> {
            AddResetClient addResetClient = new AddResetClient(ClientPluginTester.this, null);
            addResetClient.setLocationRelativeTo(ClientPluginTester.this);
            addResetClient.setVisible(true);
        });
        jm.add(jmi10);
        this.jmb.add(jm);
        this.setJMenuBar(this.jmb);
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jmb = new javax.swing.JMenuBar();
        jSplitPane1 = new javax.swing.JSplitPane();
        jScrollPane2 = new javax.swing.JScrollPane();
        jt_result = new javax.swing.JTable();
        jScrollPane1 = new javax.swing.JScrollPane();
        jta_console = new javax.swing.JTextArea();
        jPanel1 = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        jcb_connections = new javax.swing.JComboBox<>();
        jPanel2 = new javax.swing.JPanel();
        jb_run = new javax.swing.JButton();
        jb_clean = new javax.swing.JButton();
        jLabel2 = new javax.swing.JLabel();
        jb_jsonFormat = new javax.swing.JButton();
        jb_cleanConsole = new javax.swing.JButton();
        jcb_autoFormat = new javax.swing.JCheckBox();
        jPanel3 = new javax.swing.JPanel();
        jLabel3 = new javax.swing.JLabel();
        jLabel4 = new javax.swing.JLabel();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);

        jSplitPane1.setDividerLocation(-50);
        jSplitPane1.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
        jSplitPane1.setCursor(new java.awt.Cursor(java.awt.Cursor.MOVE_CURSOR));

        jScrollPane2.setAutoscrolls(true);

        jt_result.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {

            },
            new String [] {

            }
        ));
        jt_result.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
        jt_result.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mousePressed(java.awt.event.MouseEvent evt) {
                jt_resultMousePressed(evt);
            }
        });
        jScrollPane2.setViewportView(jt_result);

        jSplitPane1.setBottomComponent(jScrollPane2);

        jScrollPane1.setAutoscrolls(true);

        jta_console.setColumns(20);
        jta_console.setRows(5);
        jScrollPane1.setViewportView(jta_console);

        jSplitPane1.setLeftComponent(jScrollPane1);

        jPanel1.setBorder(javax.swing.BorderFactory.createEtchedBorder());

        jLabel1.setText("选取连接：");

        jcb_connections.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                jcb_connectionsItemStateChanged(evt);
            }
        });

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jLabel1)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jcb_connections, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(840, Short.MAX_VALUE))
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel1)
                    .addComponent(jcb_connections, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        jPanel2.setBorder(javax.swing.BorderFactory.createEtchedBorder());

        jb_run.setBackground(new java.awt.Color(255, 51, 0));
        jb_run.setForeground(new java.awt.Color(255, 255, 255));
        jb_run.setText("执行插件命令");
        jb_run.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jb_runActionPerformed(evt);
            }
        });

        jb_clean.setText("清空预执行命令");
        jb_clean.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jb_cleanActionPerformed(evt);
            }
        });

        jLabel2.setForeground(new java.awt.Color(255, 51, 51));
        jLabel2.setText("注：每次执行只能是单个插件命令");

        jb_jsonFormat.setText("返回值JSON格式化");
        jb_jsonFormat.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jb_jsonFormatActionPerformed(evt);
            }
        });

        jb_cleanConsole.setText("清空控制台");
        jb_cleanConsole.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jb_cleanConsoleActionPerformed(evt);
            }
        });

        jcb_autoFormat.setText("自动JSON格式化返回内容");

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout.setHorizontalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jb_run)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jb_jsonFormat)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jb_clean)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jb_cleanConsole)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jcb_autoFormat)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(jLabel2)
                .addContainerGap())
        );
        jPanel2Layout.setVerticalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jb_run)
                    .addComponent(jb_clean)
                    .addComponent(jLabel2)
                    .addComponent(jb_jsonFormat)
                    .addComponent(jb_cleanConsole)
                    .addComponent(jcb_autoFormat))
                .addContainerGap(10, Short.MAX_VALUE))
        );

        jPanel3.setBorder(javax.swing.BorderFactory.createEtchedBorder());

        jLabel3.setText("控制台：");

        jLabel4.setText("预处理命令：");

        javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
        jPanel3.setLayout(jPanel3Layout);
        jPanel3Layout.setHorizontalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel3Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel3)
                    .addComponent(jLabel4))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        jPanel3Layout.setVerticalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel3Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jLabel3)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(jLabel4)
                .addContainerGap())
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 894, Short.MAX_VALUE)))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 583, Short.MAX_VALUE)
                    .addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(11, 11, 11))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void jcb_connectionsItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_jcb_connectionsItemStateChanged
        if (evt.getStateChange() == ItemEvent.SELECTED) {
            String key = (String)jcb_connections.getSelectedItem();
            currentConnectionParam = this.connectData.getJSONObject(key);
        }
    }//GEN-LAST:event_jcb_connectionsItemStateChanged

    public void addPluginParam(JSONObject jo, String name){
        tm.addRow(new String[]{name, jo.toJSONString()});
    }

    public void addPluginParam(JSONObject jo, int rowIndex){
        tm.setValueAt(jo.toJSONString(), rowIndex, DATA_INDEX);
    }

    public String getConsoleData(){
        return jta_console.getText();
    }

    private void jb_runActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jb_runActionPerformed
        if(jt_result.getSelectedRowCount() < 1){
            JOptionPane.showMessageDialog(rootPane, "请选取要执行的命令行。");
            return;
        }
        if(jt_result.getSelectedRowCount() > 1){
            JOptionPane.showMessageDialog(rootPane, "每次只能执行一个命令。");
            return;
        }
        int selectedRow = jt_result.getSelectedRow();
        if(selectedRow >= 0 && selectedRow < jt_result.getRowCount()) {
            String cmdStr = (String) tm.getValueAt(selectedRow, DATA_INDEX);
            try {
                JSONObject jo = JSON.parseObject(cmdStr);
                jo.put("runner", RUNNER_TYPE);
                comSendCmd(jo.toJSONString());
            } catch (Exception e) {
                TerminalApplication.syslogInfo(e.getMessage());
                JOptionPane.showMessageDialog(rootPane, "命令格式不正确，请编辑或删除。");
            }
        }else{
            JOptionPane.showMessageDialog(rootPane, "选取执行命令有问题，请重试。");
        }
    }//GEN-LAST:event_jb_runActionPerformed

    private void jb_cleanActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jb_cleanActionPerformed
        initResultTable();
    }//GEN-LAST:event_jb_cleanActionPerformed

    private void jt_resultMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jt_resultMousePressed
        int mods = evt.getModifiers();
        if ((mods & InputEvent.BUTTON3_MASK) != 0) {
//            if (this.getExtendedState() == Frame.MAXIMIZED_BOTH) {
//                this.paramHelpJpm.show(this, evt.getX(), evt.getYOnScreen() + this.paramHelpJpm.getHeight() / 2);
//            } else {
                this.paramHelpJpm.show(this, evt.getX() + 80, evt.getYOnScreen() - 180);
//            }
        }
    }//GEN-LAST:event_jt_resultMousePressed

    private void jb_jsonFormatActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jb_jsonFormatActionPerformed
        jta_console.setText(JsonUtil.getInstance().format(jta_console.getText()));
    }//GEN-LAST:event_jb_jsonFormatActionPerformed

    private void jb_cleanConsoleActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jb_cleanConsoleActionPerformed
        jta_console.setText("");
    }//GEN-LAST:event_jb_cleanConsoleActionPerformed

    private void comSendCmd(String cmd){
        if(currentConnectionParam == null || currentConnectionParam.isEmpty()){
            JOptionPane.showMessageDialog(rootPane, "请选取连接配置。");
            return;
        }
        if(!currentConnectionParam.containsKey("com") || currentConnectionParam.getString("com").isEmpty()){
            JOptionPane.showMessageDialog(rootPane, "请选取Com口的连接配置。");
            return;
        }
        waiting();
        TerminalApplication.pool.submit(() -> {
            JSONObject com = currentConnectionParam.getJSONObject("com");
            String comName = com.getString("value");
            String btl = currentConnectionParam.getString("btl");
            String sjw = currentConnectionParam.getString("sjw");
            String tzw = currentConnectionParam.getString("tzw");
            String xyw = currentConnectionParam.getString("xyw");
            if (!sf.ccs.containsKey(comName)) {
                createComClient(comName, btl, sjw, tzw, xyw);
            }else{
                ComClient comClient = sf.ccs.get(comName);
                comClient.setOwner(this);
            }
            JSONObject command = new JSONObject();
            JSONObject jo = JSON.parseObject(cmd);
            if(jo.getIntValue("plugin") == Command.COM_COMMAND || jo.getIntValue("plugin") == Command.UDP_COMMAND){
                JSONObject client = jo.getJSONObject("client");
                if(client.containsKey("hex") && client.getBoolean("hex")){
                    client.put("command", DatatypeConverter.printHexBinary(hc.toBytes(client.getString("command"))));
                }
            }
            command.put("cmd", jo.toJSONString());
            ComClient comClient = sf.ccs.get(comName);
            comClient.send(command.toJSONString());
        });
    }

    private void waiting(){
        waitLoading.open();
    }

    private void over(){
        if(waitLoading != null) {
            waitLoading.close();
        }
    }

    private void createComClient(String comName, String btl, String sjw, String tzw, String xyw){
        sf.ccs.put(comName, new ComClient(this, new ComConnectParam(comName, Integer.parseInt(btl), Integer.parseInt(sjw), Integer.parseInt(tzw), Integer.parseInt(xyw))));
    }

    @Override
    public void appendResult(String result) {
        over();
        if (result != null) {
            if(jcb_autoFormat.isSelected()) {
                jta_console.append(JsonUtil.getInstance().format(result));
            }else{
                jta_console.append(result);
            }
            if (result != "") {
                jta_console.append("\n");
            }
            initPos();
        }
    }

    @Override
    public void appendError(String data) {
        over();
        if (data != null) {
            TerminalApplication.syslogInfo(data);
            JSONObject jsonObject = JSON.parseObject(data);
            JOptionPane.showMessageDialog(this.getRootPane(), "执行失败: " + jsonObject.getString("msg"));
        }
    }

    @Override
    public String getOwnerClassName(){
        return this.getClass().getTypeName();
    }

    private void initPos() {
        int pos = jta_console.getDocument().getLength();
        jta_console.setCaretPosition(pos);
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JSplitPane jSplitPane1;
    private javax.swing.JButton jb_clean;
    private javax.swing.JButton jb_cleanConsole;
    private javax.swing.JButton jb_jsonFormat;
    private javax.swing.JButton jb_run;
    private javax.swing.JCheckBox jcb_autoFormat;
    private javax.swing.JComboBox<String> jcb_connections;
    private javax.swing.JMenuBar jmb;
    private javax.swing.JTable jt_result;
    private javax.swing.JTextArea jta_console;
    // End of variables declaration//GEN-END:variables
}
